﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Text;
using System.Threading.Tasks;

namespace Utils.BreakHsl;

public class Refal
    {
        private static readonly BindingFlags BindingFlags = BindingFlags.Static | BindingFlags.Instance |
                                                            BindingFlags.NonPublic | BindingFlags.Public;

        public static T GetControl<T>(Type type, Object typeInstance, string fieldname)
        {
            var fieldInfo = type.GetField(fieldname, BindingFlags);
            var control = (T)fieldInfo.GetValue(typeInstance);
            return control;
        }

        public static void SetControlValue(Type type, Object typeInstance, string fieldname, object value)
        {
            var fieldInfo = type.GetField(fieldname, BindingFlags);
            fieldInfo.SetValue(typeInstance, value);
        }

        public static EventHandler GetEventHandler(Type type, Object typeInstance, string eventname)
        {
            var method = type.GetMethod(eventname, BindingFlags);
            Delegate del = Delegate.CreateDelegate(typeof(EventHandler), typeInstance, method);
            return del as EventHandler;
        }


        public static void InvokeMethod(Type type, Object typeInstance, string eventname, object[] paramters)
        {
            var method = type.GetMethod(eventname, BindingFlags);
            method.Invoke(typeInstance, paramters);
        }

        public static void ReplaceMethod(MethodInfo methodToReplace, MethodInfo methodToInject)
        {
            RuntimeHelpers.PrepareMethod(methodToReplace.MethodHandle);
            RuntimeHelpers.PrepareMethod(methodToInject.MethodHandle);

            unsafe
            {
                if (IntPtr.Size == 4)
                {
                    int* inj = (int*)methodToInject.MethodHandle.Value.ToPointer() + 2;
                    int* tar = (int*)methodToReplace.MethodHandle.Value.ToPointer() + 2;
#if DEBUG
                    Console.WriteLine("\nVersion x86 Debug\n");

                    byte* injInst = (byte*)*inj;
                    byte* tarInst = (byte*)*tar;

                    int* injSrc = (int*)(injInst + 1);
                    int* tarSrc = (int*)(tarInst + 1);

                    *tarSrc = (((int)injInst + 5) + *injSrc) - ((int)tarInst + 5);
#else
                    Console.WriteLine("\nVersion x86 Release\n");
                    *tar = *inj;
#endif
                }
                else
                {

                    long* inj = (long*)methodToInject.MethodHandle.Value.ToPointer() + 1;
                    long* tar = (long*)methodToReplace.MethodHandle.Value.ToPointer() + 1;
#if DEBUG
                    Console.WriteLine("\nVersion x64 Debug\n");
                    byte* injInst = (byte*)*inj;
                    byte* tarInst = (byte*)*tar;


                    int* injSrc = (int*)(injInst + 1);
                    int* tarSrc = (int*)(tarInst + 1);

                    *tarSrc = (((int)injInst + 5) + *injSrc) - ((int)tarInst + 5);
#else
                    Console.WriteLine("\nVersion x64 Release\n");
                    *tar = *inj;
#endif
                }
            }
        }
    }